# ----------------------------
# coding: utf-8
# 开发作者 : 钱嘉龙
# 创建日期 : 2022/2/24 13:42
# ----------------------------

import cv2 as cv
import imutils
import numpy as np
import math
import serial



show_area = 0
show_distance = 1
area_max = 26000
area_min = 8000


class Camera(object):
    @staticmethod
    # 获取本地图片
    def get_images(name):
        image = cv.imread('F:\\EngineeringDocuments\\Logistics_Handling_Robot\\images\\{0}.jpg'.format(name))
        return image

    @staticmethod
    # 获取摄像头
    def camera_get_images(cap):
        ret, image = cap.read()
        return ret, image

    @staticmethod
    # 显示指定图片
    def show_image(name, src, height, save):
        cv.namedWindow(name, cv.WINDOW_AUTOSIZE)
        if height == 0:
            pass
        else:
            src = imutils.resize(src, height=height)
        cv.imshow(name, src)
        if save:
            cv.imwrite('F:\\EngineeringDocuments\\Logistics_Handling_Robot\\images\\{0}.jpg'.format(name), src)

    @staticmethod
    # 更改图片的对比度、亮度函数     --->     c:对比度;     b:亮度;
    def contrast_brightness(image, c, b):
        height, width, channels = image.shape[0:3]
        black = np.zeros([height, width, channels], image.dtype)
        dst = cv.addWeighted(image, c, black, 1 - c, b)
        return dst

    @staticmethod
    # 二值化
    def threshold(gary):
        # ret, binary = cv.threshold(gary, 0, 255, cv.THRESH_BINARY)
        binary = cv.adaptiveThreshold(gary, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 15, 5)
        return binary

    @staticmethod
    # 高斯模糊
    def gaussian_blur(image, size):
        return cv.GaussianBlur(image, (size, size), 0)

    @staticmethod
    # 转换灰度图片
    def convert_gray_scale(image):
        return cv.cvtColor(image, cv.COLOR_BGR2GRAY)

    @staticmethod
    # 获取卷积核
    def get_kernel(model, size):
        if model == 0:
            kernel = cv.getStructuringElement(cv.MORPH_RECT, (size, size))
        else:
            kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (size, size))
        return kernel

    @staticmethod
    # 形态学操作
    def morphology_process(binary, model, kernel, times):
        if model == 0:
            open_image = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=times)
        else:
            open_image = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel, iterations=times)
        return open_image

    @staticmethod
    # 边缘检测
    def detect_edges(image, dst, low_threshold=45, high_threshold=125):
        dst_copy = dst.copy()
        canny = cv.Canny(image, low_threshold, high_threshold)
        contours = cv.findContours(canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)[0]
        for i, contour in enumerate(contours):
            area = cv.contourArea(contour)
            print(area)
            cv.drawContours(dst_copy, contours, i, (255, 255, 0), 2)
        return dst_copy, contours

    @staticmethod
    # 角点检测
    def harris_detect(gray, image):
        image_copy = image.copy()
        harris = cv.cornerHarris(gray, 10, 5, 0.04)
        image_copy[harris > 0.1 * harris.max()] = [255, 255, 255]
        return image_copy, harris

    @staticmethod
    # 获取外接矩形
    def bounding_boxes(contours, image, number):
        color = {0: 'red', 1: 'brown', 2: 'orange', 3: 'yellow', 4: 'green', 5: 'blue', 6: 'purple'}
        image_copy = image.copy()
        for i, contours in enumerate(contours):
            area = cv.contourArea(contours)
            if not(area_min < area < area_max):
                continue
            x, y, w, h = cv.boundingRect(contours)
            print(color[number])
            cv.putText(image_copy, '{0}'.format(color[number]), (x, y-10),
                       cv.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)
            mm = cv.moments(contours)
            if not(mm['m00'] == 0):
                cx = mm['m10']/mm['m00']
                cy = mm['m01']/mm['m00']
                cv.circle(image_copy, (int(cx), int(cy)), 5, (255, 255, 255), -1)
            cv.rectangle(image_copy, (x, y), (x+w, y+h), (255, 255, 255), 2)
        return image_copy

    @staticmethod
    # 获取最小外接矩形
    def min_bounding_boxes(contours, image, number):
        center = []
        radius = 0
        color = {0: 'red', 1: 'green', 2: 'blue'}
        image_copy = image.copy()
        for a, contours in enumerate(contours):
            area = cv.contourArea(contours)
            if show_area:
                print('area:', area)
            if not (area_min < area < area_max):
                continue
            # 最小外接圆
            (x, y), radius = cv.minEnclosingCircle(contours)
            center = [int(x), int(y)]
            radius = int(radius)
            # image_copy = cv.circle(image_copy, tuple(center), radius, (255, 255, 255), 5)
            image_copy = cv.circle(image_copy, tuple(center), 2, (255, 255, 255), 5)
            # image_copy = cv.circle(image_copy, (310, 150), 2, (0, 0, 255), 5)
            # 显示颜色
            cv.putText(image_copy, '{0}'.format(color[number]), (center[0] - 20, center[1] - 10),
                       cv.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
        return image_copy, center


    @staticmethod
    # 计算两点之间的距离
    def calculate_long(pts1, pts2):
        distance = math.pow((pts1[0] - pts2[0]), 2) + math.pow((pts1[1] - pts2[1]), 2)
        distance = math.sqrt(distance)
        if show_distance:
            print('distance:', distance)
        return distance
   

    @staticmethod
    def pos_adjust(center, base_point):
        # 小车向左: 1       小车向右: 2
        right_or_left = 0
        # 小车向前: 1       小车向后: 2
        front_or_behind = 0
        if center[0] < base_point[0]:
            right_or_left = 1
        else:
            right_or_left = 2
        if center[1] < base_point[1]:
            front_or_behind = 1
        else:
            front_or_behind = 2
        return right_or_left, front_or_behind


    @staticmethod
    # 串口发送小车移动方向
    def camera_move_control(right_or_left, front_or_behind):
        move = ''
        if right_or_left == 0 and front_or_behind == 0:
            move += '0'
            move += '0'
            msg = move
            ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.01)
            while True:
                for i in range(0, 2):
                    ser.write(bytes('D', encoding='utf-8'))
                    ser.write(bytes(msg, encoding='utf-8'))
                print("position is right and move control send success!")
                break
            return 1
        else:
            move += str(right_or_left)
            move += str(front_or_behind)
            msg = move
            ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.01)
            while True:
                for i in range(0, 2):
                    ser.write(bytes('D', encoding='utf-8'))
                    ser.write(bytes(msg, encoding='utf-8'))
                print("move control send success!")
                break
            return 1


